slng: rewrite plugin around the Unmute Bridge (v2)#6442
Merged
Conversation
…change reconnects
…date TTS chains, track finalize replay by actual request
tinalenguyen
left a comment
Member
There was a problem hiding this comment.
hi, thanks for the PR! could you remove the test files to prevent noise?
Contributor
Author
Done, removed the test files. Thanks! |
…guage updates to candidates
tinalenguyen
left a comment
Member
There was a problem hiding this comment.
few notes:
- removing the default for STT might surprise users, are we able to restore that or make a note of it in the README for migration?
- update_options dropped speed (tts.py:662) callers passing speed= now hit a TypeError, and speed is frozen at construction. Public API break not in the migration notes
- control_profile captured but never sent (tts.py:407) — the constructor arg / TTSConnectionConfig field is only ever emitted as a log field; never a header, never in the init payload. A user setting it gets a silent no-op.
- STT reconnect loop: no cap, backoff, or failover (stt.py:939) a graceful WS close with no buffered audio and input still open makes recv_task return False, which reconnects the same candidate with no attempt counter
…profile and prebuilt TTS candidates, cap silent STT reconnects, list-typed connections
Contributor
Author
Thanks for the thorough review, all four addressed:
|
…anup can't be dropped
…drop via bounded same-endpoint replay
…, not just connection drops
tinalenguyen
approved these changes
Jul 23, 2026
tinalenguyen
left a comment
Member
There was a problem hiding this comment.
thanks for iterating, tested it as well! this will be included in the next patch release, all plugins must be on the same version. the readme migration notes and deprecation warnings should suffice, we could also make note on our docs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Breaking change
This is a major rewrite of
livekit-plugins-slng. We would like it released as 2.0.0 (please bump accordingly at release time;version.pyis left untouched per contribution guidelines).What changed
The plugin now connects exclusively through SLNG's Unmute Bridge, the gateway's normalized protocol layer. A model identifier is all that is needed (
slng.STT(model="deepgram/nova:3")); the plugin builds the bridge WebSocket endpoint itself.model_endpoint/model_endpointsparameters were removed and now raise a clearValueErrorpointing at the replacement (model=orconnections=[...]). STT no longer defaults to a model; a model orconnectionsmust be passed explicitly.connections=[...]accepts model identifiers, bridge endpoint URLs, or typedSTTConnectionConfig/TTSConnectionConfigobjects. STT fails over at safe stream boundaries and replays buffered audio (including a pending finalize) onto the new connection; TTS fails over only before first audio. HTTP 413 is treated as terminal instead of walking the chain, since every candidate would reject the same oversized payload. Recovery back to the primary is cooldown-based.max_retryand reset on real transcript progress, so a persistently failing endpoint still surfaces the error.finalizesignal when the agent's user state transitions to listening; wire it withstt.attach_to_session(session)(or callstt.notify_user_state(...)from auser_state_changedhandler). A watchdog (final_timeout_s, opt-in) guards against providers that never deliver the final transcript. Interim results no longer disarm the watchdog.provider_api_keyforwards the customer's own provider credential as the gateway'sX-Slng-Provider-Keyheader.region_override, a newworld_part_overrideconstrains routing to a broad geographic zone (maps to the gateway'sX-World-Part-Overrideheader;region_overridetakes precedence). Both propagate to fallback candidates.slng_eventemits structured events for gateway session IDs and fallback attempt / switch / exhaustion.hi-IN). Voice IDs are provider-native.pcm_s16leSTT input is accepted (previously other encodings were silently mislabeled),recognize()raisesNotImplementedError(the bridge is WebSocket-only), andoffline_recognizeis reported asFalse.async forandcollect(), per-run stream state so base-class retries produce audio, consistent watchdog and speech-event state across options-change reconnects, runtime voice/language/speed updates that propagate to fallback candidates and safely invalidate warm-standby connections, a bounded cap on silent reconnects, and no leaked connection or timing state.Testing
make checkpasses: ruff format, ruff lint, and strict mypy viascripts/check_types.py.Notes for reviewers
README.mdwas rewritten to document the 2.0 API, including a "Migrating from 1.x" section.synthesize()and the streaming path treat a server close after audio was received as end-of-segment deliberately: several bridge providers (Rime, Cartesia) terminate segments via close.